package ags.muse.recon;

import java.util.HashMap;
import java.util.Map;

import ags.muse.base.Rules;
import ags.muse.recon.events.ReconEvent;
import ags.util.points.*;

public abstract class Robot {
	// Final attributes
	private final String name;
	private final boolean isEnemy;
	private final boolean isTeammate;
	private final boolean isSelf;
	private final SelfRobot self;

	// Final attribute getters
	public String getName() { return name; }
	public boolean isEnemy() { return isEnemy; }
	public boolean isTeammate() { return isTeammate; }
	public boolean isSelf() { return isSelf; }

	// Dynamic attributes
	private AbsolutePoint location;
	private RelativePoint velocity;
	private double energy;
	private long time = -1;
	private RobotHistory history;
	private HashMap<String, Double> distances;

	// Dynamic attribute getters
	public AbsolutePoint getLocation() { return location; }
	public RelativePoint getVelocity() { return velocity; }
	public double getEnergy() { return energy; }
	public long getTime() { return time; }
	public RobotHistory getHistory() { return history; }
	public double getDistance(String botname) {
		Double dist = distances.get(botname);
		if (dist == null) {
			dist = 0.0;
		}
		return dist;
	}
	public double getClosestDist() {
		double bestDist = Double.POSITIVE_INFINITY;
		for (Map.Entry<String, Double> entry : distances.entrySet()) {
			if (entry.getValue() < bestDist) {
				bestDist = entry.getValue();
			}
		}
		return bestDist;
	}
	
	// Protected distance setters
	protected void clearDistances() { distances.clear(); }
	protected void setDistance(String botname, double distance) { distances.put(botname, distance); }

	public Robot(Rules rules, SelfRobot self, String name) {
		// Set name
		this.name = name;

		// Set self
		this.self = self;
		
		this.distances = new HashMap<String, Double>();

		// Set self/enemy/teammate values
		if (rules.NAME == name) {
			isSelf = true;
			isTeammate = false;
			isEnemy = false;
		} else if (rules.isTeammate(name)) {
			isSelf = false;
			isTeammate = true;
			isEnemy = false;
		} else {
			isSelf = false;
			isTeammate = false;
			isEnemy = true;
		}
	}

	public boolean update(ReconEvent event) {
		if (event.getName() == getName() && event.getTime() > getTime()) {
			location = event.getLocation();
			velocity = event.getVelocity();
			energy = event.getEnergy();
			time = event.getTime();
			if (history != null) {
				history = history.update(location, velocity, energy, time);
			}
			else {
				history = new RobotHistory(location, velocity, energy, time, null, null);
			}
			return true;
		}
		return false;
	}

	public long getDataAge() {
		if (self != null) {
			return (self.getTime() - getTime());
		} else {
			return 0;
		}
	}
}
